Page({
  data: {
    raceTime: '',
    raceTimeDisplay: '',
    raceLocation: '',
    showTimeModal: false,
    years: [],
    months: [],
    days: [],
    datePickerValue: [0, 0, 0],
    startTime: '16:00',
    endTime: '18:00',
    signupList: [null, null, null, null, null, null, null, null],
    signupCount: 0,
    showSignupAction: false,
    signupIndex: -1,
    showMatchModal: false,
    girlSetting: 'standard',
    matchCount: 9,
    matchList: [],
    disclaimerChecked: true,
    selectedItemIndex: 0,
    scoreModalVisible: false,
    scoreModalIndex: -1,
    scoreLeft: '',
    scoreRight: '',
    scoreModalLeft: [],
    scoreModalRight: [],
    resultList: [],
    userInfo: null,
    courtCount: 1,
    maxCourtCount: 1,
    safePaddingTop: 0,
    showGenderSelect: false,
    tempOtherName: '',
    tempOtherGender: 'male',
    showEditTitleModal: false,
    editTitleValue: '',
    raceTitle: '',
    defaultRaceTitle: '多人轮转赛 | 7-3发布',
    showOtherSignupModal: false,
    finishedCount: 0,
    scoreTabIndex: 0,
    scoreTabList: [
      { title: '全部', count: 0 },
      { title: '未结束', count: 0 },
      { title: '可以比赛', count: 0 },
      { title: '比赛中', count: 0 }
    ],
    filteredMatchList: [],
    showRegenMatchBtn: false,
    maxPlayers: 8,
    appliedCount: 0,
    recommendMatchCountList: [], // 新增：推荐局数列表
    isCustomMatchCount: false,
    customMatchCount: '',
    showQuickSignupModal: false,
    quickSignupText: '',
    quickSignupPreviewPages: [],
    quickSignupPreviewPageIndex: 0,
    quickSignupPreviewPageSize: 15,
    editSignupIndex: -1, // 新增：编辑报名时记录索引
    editSignupName: '', // 新增：编辑报名时记录昵称
    editSignupGender: 'male', // 新增：编辑报名时记录性别
    showEditSignupModal: false, // 新增：编辑报名弹窗是否显示
    modalOpen: false, // 防止多次弹窗
    raceInfo: null,
    shareImagePath: '', // 存储生成的分享图路径
    shareTitle: '羽毛球比赛邀请',
    sharePath: '/pages/raceEnroll/raceEnroll',
    isCreator: false // 是否为创建人
  },
  onLoad(options) {
    if (!options.id) {
      wx.showToast({ title: '缺少比赛ID', icon: 'none' });
      setTimeout(() => wx.navigateBack(), 1500);
      return;
    }
    this.options = options;
    this.raceId = options.id;
    
    // 引入本地数据管理器
    const localDataManager = require('../../utils/localDataManager.js');
    this.localDataManager = localDataManager;
    
    // 获取系统状态栏和导航栏高度
    wx.getWindowInfo({
      success: res => {
        const statusBarHeight = res.statusBarHeight || 20;
        const navBarHeight = 44; // 可根据实际微调
        this.setData({
          safePaddingTop: statusBarHeight + navBarHeight
        });
      }
    });
    
    // 从本地存储加载比赛基本信息
    const raceId = options.id;
    const raceData = localDataManager.getRace(raceId);
    
    if (raceData) {
      let selectedItemIndex = 0;
      let showRegenMatchBtn = false;
      if (raceData.status === '计分中') {
        selectedItemIndex = 1;
        showRegenMatchBtn = true;
      } else if (raceData.status === '已完赛') {
        selectedItemIndex = 2;
        showRegenMatchBtn = true;
      }
      
      // 判断是否为创建人
      const app = getApp();
      const currentUser = app.globalData.userInfo;
      const isCreator = currentUser && raceData.creator && 
                       (currentUser.userId === raceData.creator.userId || 
                        currentUser.phone === raceData.creator.phone);
      
      this.setData({
        raceTitle: raceData.title || '',
        raceTimeDisplay: raceData.dateStr || '',
        raceLocation: raceData.location || '',
        selectedItemIndex,
        showRegenMatchBtn,
        maxPlayers: raceData.maxPlayers || 8,
        courtCount: raceData.courtCount || 1,
        isCreator: isCreator,
        raceInfo: {
          name: raceData.title || '',
          dateStr: raceData.dateStr || '',
          location: raceData.location || '',
          totalNum: raceData.maxPlayers || 8
        }
      }, () => {
        this.loadSignupList();
      });
      console.log('比赛信息加载', raceData);
      console.log('是否为创建人:', isCreator);
    } else {
      wx.showToast({ title: '比赛不存在', icon: 'none' });
      setTimeout(() => wx.navigateBack(), 1500);
    }
    const date = new Date();
    const years = [];
    for (let i = date.getFullYear(); i <= date.getFullYear() + 2; i++) years.push(i);
    const months = [];
    for (let i = 1; i <= 12; i++) months.push(i);
    const days = this.getDaysInMonth(date.getFullYear(), date.getMonth() + 1);
    const datePickerValue = [0, date.getMonth(), date.getDate() - 1];
    this.setData({ years, months, days, datePickerValue, signupCount: 0 });
    const app = getApp();
    if (app.globalData.userInfo) {
      this.setData({ userInfo: app.globalData.userInfo });
    }
    this.updateCourtCountLimit();
    this.loadMatchList();
  },
  getDynamicRaceTitle(maxPlayers, dateStr) {
    return `${maxPlayers}人多人轮转赛 | ${dateStr || ''}`;
  },
  getDefaultRaceTitle(dateStr) {
    return `多人轮转赛 | ${dateStr || ''}`;
  },
  getDaysInMonth(year, month) {
    const days = [];
    const dayCount = new Date(year, month, 0).getDate();
    for (let i = 1; i <= dayCount; i++) days.push(i);
    return days;
  },
  // 生成海报
  async generatePoster() {
    try {
      const ctx = wx.createCanvasContext('posterCanvas', this);
      
      // 1. 绘制背景
      ctx.setFillStyle('#ffffff');
      ctx.fillRect(0, 0, 300, 500);
      
      // 2. 绘制内容（添加错误处理）
      //await this.drawImageWithFallback(ctx, '/images/badminton.jpeg', 20, 20, 260, 260);
      
      // 3. 绘制文字
      ctx.setFontSize(18);
      ctx.setFillStyle('#333333');
      ctx.fillText('羽毛球比赛', 30, 300);
      
      // 4. 生成临时文件
      const tempFilePath = await new Promise((resolve, reject) => {
        ctx.draw(false, () => {
          setTimeout(() => {
            wx.canvasToTempFilePath({
              canvasId: 'posterCanvas',
              success: (res) => resolve(res.tempFilePath),
              fail: reject
            }, this);
          }, 300);
        });
      });
      
      this.setData({ tempFilePath, posterReady: true });
      return tempFilePath;
      
    } catch (err) {
      console.error('生成海报失败:', err);
      throw err;
    }
  },

  // 带错误处理的图片绘制
  drawImageWithFallback(ctx, imgPath, x, y, width, height) {
    return new Promise((resolve) => {
      wx.getImageInfo({
        src: imgPath,
        success: (res) => {
          ctx.drawImage(res.path, x, y, width, height);
          resolve();
        },
        fail: (err) => {
          console.error('图片加载失败:', imgPath, err);
          // 绘制默认背景
          ctx.setFillStyle('#f0f0f0');
          ctx.fillRect(x, y, width, height);
          resolve();
        }
      });
    });
  },

  // 点击分享按钮
  async handleShare() {
    if (!this.data.tempFilePath) {
      wx.showLoading({ title: '生成分享图中...' });
      try {
        await this.generatePoster();
      } catch (err) {
        wx.showToast({ title: '生成分享图失败', icon: 'none' });
        wx.hideLoading();
        return;
      }
      wx.hideLoading();
    }
    
  },

  // 分享配置
  onShareAppMessage() {
    const id = this.data.raceId || (this.options && this.options.id) || '';
    return {
      title: this.data.shareTitle,
      path: `/pages/raceEnroll/raceEnroll?id=${id}`
      // 不设置 imageUrl，让微信自动生成页面内容卡片
    };
  },
  // 朋友圈分享
  onShareTimeline() {
    const id = this.data.raceId || (this.options && this.options.id) || '';
    return {
      title: this.data.shareTitle,
      query: `id=${id}&from=timeline`
      // 不设置 imageUrl
    };
  },
  onEditTime() {
    if (!this.data.isCreator) {
      wx.showToast({ title: '只有创建人才能修改', icon: 'none' });
      return;
    }
    this.setData({ showTimeModal: true });
  },
  onCloseTimeModal() {
    this.setData({ showTimeModal: false });
  },
  onDateChange(e) {
    const { years, months } = this.data;
    const [yearIdx, monthIdx, dayIdx] = e.detail.value;
    const year = years[yearIdx];
    const month = months[monthIdx];
    const days = this.getDaysInMonth(year, month);
    let newDayIdx = dayIdx;
    if (dayIdx >= days.length) newDayIdx = days.length - 1;
    this.setData({
      datePickerValue: [yearIdx, monthIdx, newDayIdx],
      days
    });
  },
  onStartTimeChange(e) {
    this.setData({ startTime: e.detail.value });
  },
  onEndTimeChange(e) {
    this.setData({ endTime: e.detail.value });
  },
  onConfirmTime() {
    const { years, months, days, datePickerValue, startTime, endTime } = this.data;
    const year = years[datePickerValue[0]];
    const month = months[datePickerValue[1]];
    const day = days[datePickerValue[2]];
    const dateStr = `${year}-${month < 10 ? '0'+month : month}-${day < 10 ? '0'+day : day}`;
    const display = `${dateStr} ${startTime} 至 ${endTime}`;
    const raceId = this.options && this.options.id;

    // 更新本地存储中的比赛信息
    const raceData = this.localDataManager.getRace(raceId);
    if (raceData) {
      raceData.dateStr = display;
      this.localDataManager.saveRace(raceData);
      
      wx.showToast({ title: '时间已更新' });
      this.setData({
        raceTime: `${dateStr} ${startTime}-${endTime}`,
        raceTimeDisplay: display,
        showTimeModal: false
      });
    } else {
      wx.showToast({ title: '比赛不存在', icon: 'none' });
    }
  },
  onEditLocation() {
    if (!this.data.isCreator) {
      wx.showToast({ title: '只有创建人才能修改', icon: 'none' });
      return;
    }
    
    wx.showModal({
      title: '编辑比赛地点',
      content: this.data.raceLocation || '',
      placeholderText: '请输入比赛地点',
      editable: true,
      success: (res) => {
        if (res.confirm && res.content) {
          const newLocation = res.content.trim();
          if (newLocation) {
            this.setData({
              raceLocation: newLocation
            });
            
            // 更新比赛信息
            const raceData = this.localDataManager.getRace(this.raceId);
            if (raceData) {
              raceData.location = newLocation;
              this.localDataManager.saveRace(raceData);
            }
            
            wx.showToast({ title: '地点修改成功', icon: 'success' });
          }
        }
      }
    });
  },
  // ======= 登录授权统一处理 =======
  ensureLogin(callback) {
    let userInfo = this.data.userInfo || getApp().globalData.userInfo;
    if (userInfo) {
      if (typeof callback === 'function') callback();
      return;
    }
    wx.showModal({
      title: '温馨提示',
      content: '你还未登录，请登录后再进行操作',
      confirmText: '登录',
      cancelText: '取消',
      success: (res) => {
        if (res.confirm) {
          wx.getUserProfile({
            desc: '用于完善会员资料',
            success: res => {
              getApp().globalData.userInfo = res.userInfo;
              this.setData({ userInfo: res.userInfo });
              wx.showToast({ title: '登录成功', icon: 'success' });
              if (typeof callback === 'function') callback();
            },
            fail: err => {
              wx.showToast({ title: '微信授权失败', icon: 'none' });
            }
          });
        }
        // 取消时什么都不做
      }
    });
  },
  onSignupTap(e) {
    const index = e.currentTarget.dataset.index;
    const { signupList } = this.data;
    this.ensureLogin(() => {
      let currentUser = this.data.userInfo || getApp().globalData.userInfo;
      const item = signupList[index];
      
      if (!item || !item.nickName || !item._id) {
        // 检查当前用户是否已经报名
        const hasSigned = signupList.some(signup => 
          signup && signup.nickName === currentUser.nickName
        );
        
        this.setData({ 
          showSignupAction: true, 
          signupIndex: index, 
          hasSigned: hasSigned 
        });
        return;
      }
      
      wx.showActionSheet({
        itemList: ['编辑', '取消报名'],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.setData({
              editSignupIndex: index,
              editSignupName: item.nickName,
              editSignupGender: item.gender || 'male',
              showEditSignupModal: true
            });
          } else if (res.tapIndex === 1) {
            wx.showModal({
              title: '取消报名',
              content: '确定要取消该报名吗？',
              confirmText: '取消报名',
              cancelText: '关闭',
              success: (modalRes) => {
                if (modalRes.confirm) {
                  const raceId = this.options && this.options.id;
                  
                  // 从本地存储中删除报名
                  this.localDataManager.removeSignup(raceId, item._id);
                  wx.showToast({ title: '已取消报名' });
                  
                  // 更新比赛信息
                  const raceData = this.localDataManager.getRace(raceId);
                  if (raceData) {
                    raceData.courtCount = this.data.courtCount;
                    this.localDataManager.saveRace(raceData);
                  }
                  
                  this.loadSignupList();
                }
              }
            });
          }
        }
      });
    });
  },
  onCloseSignupAction() {
    this.setData({ 
      showSignupAction: false, 
      signupIndex: -1, 
      hasSigned: false 
    });
  },
  updateSignupCount() {
    const count = this.data.signupList.filter(item => item).length;
    this.setData({ signupCount: count });
    this.updateCourtCountLimit();
  },
  onSignupSelf() {
    this.ensureLogin(() => {
      let userInfo = this.data.userInfo || getApp().globalData.userInfo;
      const { signupIndex } = this.data;
      const raceId = this.options && this.options.id;
      
      // 兼容微信用户信息的 gender 字段（1男2女0未知）和字符串格式
      let gender = 'male';
      if (userInfo.gender === 2 || userInfo.gender === 'female') {
        gender = 'female';
      } else if (userInfo.gender === 1 || userInfo.gender === 'male') {
        gender = 'male';
      } else {
        // 如果性别未知，默认为男性
        gender = 'male';
      }
      
      // 根据性别设置头像
      let avatarUrl = userInfo.avatarUrl;
      if (gender === 'female') {
        avatarUrl = '../../images/avatar_girl.png';
      } else if (gender === 'male') {
        avatarUrl = '../../images/avatar_boy.png';
      }
      
      // 使用点击的位置作为order，保持位置不变
      const order = signupIndex;
      
      // 添加到本地存储
      const signupData = {
        raceId,
        order: order,
        userInfo: {
          nickName: userInfo.nickName,
          avatarUrl: avatarUrl,
          gender: gender
        }
      };
      
      this.localDataManager.addSignup(raceId, signupData);
      wx.showToast({ title: '报名成功' });
      
      // 更新比赛信息
      const raceData = this.localDataManager.getRace(raceId);
      if (raceData) {
        raceData.courtCount = this.data.courtCount;
        this.localDataManager.saveRace(raceData);
      }
      
      this.setData({ showSignupAction: false, signupIndex: -1 }, () => {
        this.loadSignupList();
      });
    });
  },
  onSignupOther() {
    this.setData({
      showOtherSignupModal: true,
      tempOtherName: '',
      tempOtherGender: 'male'
    });
  },
  onOtherNameInput(e) {
    this.setData({
      tempOtherName: e.detail.value
    });
  },
  onSelectGender(e) {
    this.setData({
      tempOtherGender: e.currentTarget.dataset.gender
    });
  },
  onConfirmOtherSignup() {
    const { signupIndex, tempOtherName, tempOtherGender } = this.data;
    if (!tempOtherName.trim()) {
      wx.showToast({ title: '请输入姓名', icon: 'none' });
      return;
    }
    const raceId = this.options && this.options.id;
    let avatarUrl = '../../images/avatar_boy.png';
    if (tempOtherGender === 'female') {
      avatarUrl = '../../images/avatar_girl.png';
    }
    // 使用点击的位置作为order，保持位置不变
    const order = signupIndex;
    
    // 添加到本地存储
    const signupData = {
      raceId,
      order: order,
      userInfo: {
        nickName: tempOtherName,
        avatarUrl: avatarUrl,
        gender: tempOtherGender
      }
    };
    
    this.localDataManager.addSignup(raceId, signupData);
    wx.showToast({ title: '报名成功' });
    
    // 更新比赛信息
    const raceData = this.localDataManager.getRace(raceId);
    if (raceData) {
      raceData.courtCount = this.data.courtCount;
      this.localDataManager.saveRace(raceData);
    }
    
    this.setData({
      showOtherSignupModal: false,
      showSignupAction: false,
      signupIndex: -1,
      tempOtherName: '',
      tempOtherGender: 'male'
    }, () => {
      this.loadSignupList();
    });
  },
  onCancelOtherSignup() {
    this.setData({
      showOtherSignupModal: false,
      showSignupAction: false,
      signupIndex: -1,
      hasSigned: false,
      tempOtherName: '',
      tempOtherGender: 'male'
    });
  },
  onAddGroup() {
    let maxPlayers = this.data.maxPlayers + 1;
    // 本地补齐空位
    let signupList = (this.data.signupList || []).slice();
    while (signupList.length < maxPlayers) {
      signupList.push(null);
    }
    this.setData({
      maxPlayers,
      signupList
    });
    const raceId = this.options && this.options.id;
    const courtCount = this.data.courtCount;
    wx.cloud.database().collection('yuqiu').doc(raceId).update({
      data: { maxPlayers, courtCount },
      fail: () => {
        wx.showToast({ title: '更新失败', icon: 'none' });
        // 回滚
        this.setData({
          maxPlayers: this.data.maxPlayers - 1,
          signupList: signupList.slice(0, this.data.maxPlayers - 1)
        });
      }
    });
  },
  onRemoveGroup() {
    let maxPlayers = this.data.maxPlayers;
    if (maxPlayers <= 4) {
      wx.showToast({ title: '最少4人', icon: 'none' });
      return;
    }
    maxPlayers -= 1;
    // 本地裁剪空位
    let signupList = (this.data.signupList || []).slice(0, maxPlayers);
    this.setData({
      maxPlayers,
      signupList
    });
    const raceId = this.options && this.options.id;
    const courtCount = this.data.courtCount;
    wx.cloud.database().collection('yuqiu').doc(raceId).update({
      data: { maxPlayers, courtCount },
      fail: () => {
        wx.showToast({ title: '更新失败', icon: 'none' });
        // 回滚
        this.setData({
          maxPlayers: this.data.maxPlayers + 1,
          signupList: (this.data.signupList || []).concat([null])
        });
      }
    });
  },
  reloadRaceInfoAndSignup() {
    const raceId = this.options && this.options.id;
    wx.cloud.database().collection('yuqiu').doc(raceId).get({
      success: res => {
        const data = res.data || {};
        this.setData({
          maxPlayers: data.maxPlayers || 8,
          // courtCount: data.courtCount || 1   // 自动修正：去掉，避免覆盖
        }, () => {
          this.loadSignupList();
        });
      }
    });
  },
  onOpenDisclaimer() {
    wx.navigateTo({ url: '/pages/disclaimer/disclaimer' });
  },
  // 公平轮换分组算法，强制任何选手不得连续参赛或连续休息超过2场，休息和参赛分布均匀
  generateFairRotation(players, totalMatches, courts) {
    const n = players.length;
    let matchList = [];
    
    // 计算每个人应该参赛的次数
    const totalPlayerSlots = totalMatches * 4; // 每场比赛4个位置
    const avgMatchesPerPerson = Math.floor(totalPlayerSlots / n);
    const extraSlots = totalPlayerSlots % n;
    
    // 为每个人分配目标参赛次数
    let targetMatches = Array(n).fill(avgMatchesPerPerson);
    for (let i = 0; i < extraSlots; i++) {
      targetMatches[i]++;
    }
    
    console.log('目标分配:', {
      totalMatches,
      totalPlayerSlots,
      avgMatchesPerPerson,
      extraSlots,
      targetMatches
    });
    
    // 记录每个人已参赛场次
    let playCount = Array(n).fill(0);
    
    // 生成比赛
    let round = 0;
    while (matchList.length < totalMatches) {
      // 为每个场地生成比赛
      for (let c = 0; c < courts; c++) {
        if (matchList.length >= totalMatches) break;
        
        // 计算每个人的优先级分数
        let availablePlayers = playCount.map((cnt, idx) => {
          const deficit = targetMatches[idx] - cnt;
          const priority = deficit > 0 ? deficit * 1000 + (targetMatches[idx] - cnt) : cnt; // 还差场次的人优先级更高
          return {
            cnt, 
            idx, 
            target: targetMatches[idx],
            deficit,
            priority
          };
        })
        .sort((a, b) => {
          // 优先选择还差场次最多的人
          if (a.deficit > 0 && b.deficit <= 0) return -1;
          if (a.deficit <= 0 && b.deficit > 0) return 1;
          if (a.deficit > 0 && b.deficit > 0) {
            // 都还差场次，优先选择还差场次最多的人
            if (a.deficit !== b.deficit) return b.deficit - a.deficit;
          }
          // 如果都达到目标或都还没达到，选择参赛次数最少的人
          if (a.cnt !== b.cnt) return a.cnt - b.cnt;
          // 最后随机排序
          return Math.random() - 0.5;
        });
        
        // 选择前4个选手
        const selectedIndices = availablePlayers.slice(0, 4).map(p => p.idx);
        
        // 创建比赛
        const match = {
          left: selectedIndices.slice(0, 2).map(idx => players[idx]).filter(Boolean),
          right: selectedIndices.slice(2, 4).map(idx => players[idx]).filter(Boolean),
          status: 'ready',
          round: round + 1,
          courtIndex: c
        };
        
        // 确保比赛有效（每边至少1人）
        if (match.left.length >= 1 && match.right.length >= 1) {
          matchList.push(match);
          
          // 增加参赛次数
          selectedIndices.forEach(idx => {
            if (idx !== undefined && idx < n) {
              playCount[idx]++;
            }
          });
          
          console.log(`第${matchList.length}场比赛:`, {
            selectedIndices,
            playCount: [...playCount],
            targetMatches: [...targetMatches]
          });
        }
      }
      round++;
      
      // 防止无限循环
      if (round > totalMatches * 3) break;
    }
    
    // 验证分配结果
    const finalDeviation = playCount.map((cnt, idx) => Math.abs(cnt - targetMatches[idx]));
    const maxDeviation = Math.max(...finalDeviation);
    
    console.log('最终分配结果:', {
      totalMatches: matchList.length,
      playCount,
      targetMatches,
      deviation: finalDeviation,
      maxDeviation
    });
    
    // 如果最大偏差超过1，尝试重新分配
    if (maxDeviation > 1 && matchList.length > 0) {
      console.log('检测到不公平分配，尝试重新平衡...');
      return this.generateBalancedRotation(players, totalMatches, courts, targetMatches);
    }
    
    return matchList.slice(0, totalMatches);
  },

  // 新增：平衡分配算法
  generateBalancedRotation(players, totalMatches, courts, targetMatches) {
    const n = players.length;
    let matchList = [];
    let playCount = Array(n).fill(0);
    
    // 创建所有可能的4人组合
    let allCombinations = [];
    for (let i = 0; i < n; i++) {
      for (let j = i + 1; j < n; j++) {
        for (let k = j + 1; k < n; k++) {
          for (let l = k + 1; l < n; l++) {
            allCombinations.push([i, j, k, l]);
          }
        }
      }
    }
    
    // 为每个组合计算公平性分数
    allCombinations = allCombinations.map(combo => {
      const tempPlayCount = [...playCount];
      combo.forEach(idx => tempPlayCount[idx]++);
      
      const deviation = tempPlayCount.map((cnt, idx) => 
        Math.abs(cnt - targetMatches[idx])
      );
      const maxDeviation = Math.max(...deviation);
      const avgDeviation = deviation.reduce((sum, d) => sum + d, 0) / deviation.length;
      
      return {
        combo,
        maxDeviation,
        avgDeviation,
        score: maxDeviation * 1000 + avgDeviation // 优先考虑最大偏差
      };
    });
    
    // 按分数排序，选择最公平的组合
    allCombinations.sort((a, b) => a.score - b.score);
    
    // 生成比赛
    for (let matchIndex = 0; matchIndex < totalMatches; matchIndex++) {
      if (allCombinations.length === 0) break;
      
      const bestCombo = allCombinations[0];
      const selectedIndices = bestCombo.combo;
      
      const match = {
        left: selectedIndices.slice(0, 2).map(idx => players[idx]).filter(Boolean),
        right: selectedIndices.slice(2, 4).map(idx => players[idx]).filter(Boolean),
        status: 'ready',
        round: matchIndex + 1,
        courtIndex: matchIndex % courts
      };
      
      if (match.left.length >= 1 && match.right.length >= 1) {
        matchList.push(match);
        
        // 更新参赛次数
        selectedIndices.forEach(idx => {
          if (idx !== undefined && idx < n) {
            playCount[idx]++;
          }
        });
        
        // 重新计算剩余组合的分数
        allCombinations = allCombinations.slice(1).map(combo => {
          const tempPlayCount = [...playCount];
          combo.combo.forEach(idx => tempPlayCount[idx]++);
          
          const deviation = tempPlayCount.map((cnt, idx) => 
            Math.abs(cnt - targetMatches[idx])
          );
          const maxDeviation = Math.max(...deviation);
          const avgDeviation = deviation.reduce((sum, d) => sum + d, 0) / deviation.length;
          
          return {
            ...combo,
            maxDeviation,
            avgDeviation,
            score: maxDeviation * 1000 + avgDeviation
          };
        });
        
        allCombinations.sort((a, b) => a.score - b.score);
      }
    }
    
    console.log('平衡分配结果:', {
      totalMatches: matchList.length,
      playCount,
      targetMatches,
      deviation: playCount.map((cnt, idx) => Math.abs(cnt - targetMatches[idx]))
    });
    
    return matchList;
  },
  onGenerateMatch() {
    if (!this.data.isCreator) {
      wx.showToast({ title: '只有创建人才能生成对阵', icon: 'none' });
      return;
    }
    // 自动推荐局数
    const n = this.data.signupList.filter(item => item).length;
    const c = this.data.courtCount;
    let recommendList = [];
    
    // 计算每人平均打几场的推荐局数
    // 确保每人平均场次是整数
    const targetMatchesPerPerson = [3, 4, 5]; // 每人目标场次：3场、4场、5场
    
    for (let target of targetMatchesPerPerson) {
      // 计算满足每人平均打target场的最小局数
      const totalSlots = target * n; // 总位置数
      const minTotalMatches = Math.ceil(totalSlots / (4 * c)) * c;
      
      // 验证这个局数是否真的能让每人平均打整数场次
      const actualAvgMatchesPerPerson = (minTotalMatches * 4) / n;
      
      // 只有当实际平均场次是整数时才推荐（不允许小数点）
      if (actualAvgMatchesPerPerson >= target && Math.abs(actualAvgMatchesPerPerson - Math.round(actualAvgMatchesPerPerson)) < 0.01) {
        // 避免重复添加
        if (!recommendList.includes(minTotalMatches)) {
          recommendList.push(minTotalMatches);
          // 最多显示3个选项
          if (recommendList.length >= 3) {
            break;
          }
        }
      }
    }
    
    // 如果第一个循环没有找到足够的选项，继续寻找更多选项
    if (recommendList.length < 3) {
      // 尝试不同的场数，确保每人平均场次是整数
      for (let matches = 3; matches <= 20; matches++) {
        const totalSlots = matches * 4; // 总位置数
        const avgMatchesPerPerson = totalSlots / n;
        
        // 检查是否能整除（每人平均场次是整数）
        if (Math.abs(avgMatchesPerPerson - Math.round(avgMatchesPerPerson)) < 0.01 && avgMatchesPerPerson >= 2) {
          // 避免重复添加
          if (!recommendList.includes(matches)) {
            recommendList.push(matches);
            // 最多显示3个选项
            if (recommendList.length >= 3) {
              break;
            }
          }
        }
      }
    }
    
    // 如果推荐列表为空，至少添加一个基础局数
    if (recommendList.length === 0) {
      const baseMatches = Math.ceil((3 * n) / (4 * c)) * c;
      recommendList.push(baseMatches);
    }
    
    // 对推荐列表进行排序，确保按数字大小顺序显示
    recommendList.sort((a, b) => a - b);
    
    console.log('推荐局数计算:', {
      n, c, targetMatchesPerPerson,
      recommendList,
      explanation: recommendList.map(matches => {
        const avgMatches = (matches * 4) / n;
        return `${matches}场 = 每人平均${avgMatches.toFixed(1)}场`;
      })
    });

    // 如果当前选择的场数不在新的推荐列表中，就选择第一个推荐值
    let newMatchCount = recommendList[0] || 3;
    if (recommendList.length > 0 && !recommendList.includes(this.data.matchCount)) {
      newMatchCount = recommendList[0];
    } else if (recommendList.length > 0) {
      newMatchCount = this.data.matchCount; // 保持当前选择
    }
    
    this.setData({
      recommendMatchCountList: recommendList,
      matchCount: newMatchCount
    });
    if (this.data.showRegenMatchBtn) {
      wx.showModal({
        title: '提示',
        content: '重新生成对阵？现有对局和成绩将全部清除',
        confirmText: '确定',
        cancelText: '取消',
        success: (res) => {
          if (res.confirm) {
            this.setData({ showMatchModal: true });
          }
        }
      });
    } else {
      this.setData({ showMatchModal: true });
    }
  },
  onConfirmMatchModal() {
    this._doGenerateMatch();
    this.setData({ showMatchModal: false });
  },
  _doGenerateMatch() {
    // 校验报名人数
    if (this.data.signupCount < 4) {
      wx.showToast({
        title: '至少需要4人才能生成对阵',
        icon: 'none'
      });
      return;
    }
    // 校验免责声明
    if (!this.data.disclaimerChecked) {
      wx.showToast({
        title: '请先勾选免责声明',
        icon: 'none'
      });
      return;
    }
    // 生成对阵数据
    const players = this.data.signupList.filter(item => item);
    
    const totalMatches = this.data.matchCount || 3; // 用户选择的总场数
    const courts = this.data.courtCount;
    const matchList = this.generateFairRotation(players, totalMatches, courts);
    // 清空比分和状态
    matchList.forEach(match => {
      match.score = null;
      match.status = 'ready';
    });
    const raceId = this.raceId;
    
    // 保存到本地存储
    this.localDataManager.saveMatches(raceId, [{ raceId, matchList }]);
    
    // 更新比赛信息
    const raceData = this.localDataManager.getRace(raceId);
    if (raceData) {
      raceData.status = '计分中';
      raceData.matchList = matchList;
      this.localDataManager.saveRace(raceData);
    }
    
    wx.showToast({ title: '对阵已生成' });
    this.loadMatchList();
    this.setData({
      selectedItemIndex: 1
    });
  },
  onCloseMatchModal() {
    this.setData({ showMatchModal: false });
  },
  onSelectGirlSetting(e) {
    this.setData({ girlSetting: e.currentTarget.dataset.value });
  },
  onSelectMatchCount(e) {
    const val = e.detail.value;
    if (val === 'custom') {
      this.setData({ isCustomMatchCount: true, matchCount: Number(this.data.customMatchCount) || 0 });
    } else {
      this.setData({ isCustomMatchCount: false, matchCount: Number(val) });
    }
  },
  onCustomMatchCountInput(e) {
    const val = e.detail.value;
    this.setData({
      customMatchCount: val,
      isCustomMatchCount: true,
      matchCount: Number(val) || 0
    });
  },
  onStartMatch(e) {
    const filteredIndex = e.currentTarget.dataset.index;
    const { filteredMatchList, matchList } = this.data;
    const target = filteredMatchList[filteredIndex];
    // 用选手昵称拼接唯一定位
    const leftNames = target.left.map(p => p.nickName).join(',');
    const rightNames = target.right.map(p => p.nickName).join(',');
    const realIndex = matchList.findIndex(item =>
      item.left.map(p => p.nickName).join(',') === leftNames &&
      item.right.map(p => p.nickName).join(',') === rightNames
    );
    if (realIndex === -1) return;
    matchList[realIndex].status = 'playing';
    this.setData({ matchList }, () => {
      this.filterMatchList();
    });
    // 同步到数据库
    const raceId = this.options && this.options.id;
    wx.cloud.database().collection('match').where({ raceId }).get({
      success: res => {
        if (res.data.length) {
          wx.cloud.database().collection('match').doc(res.data[0]._id).update({
            data: { matchList },
            success: () => {
              this.filterMatchList();
            }
          });
        }
      }
    });
  },
  onCancelMatch(e) {
    const filteredIndex = e.currentTarget.dataset.index;
    const { filteredMatchList, matchList } = this.data;
    const target = filteredMatchList[filteredIndex];
    // 用选手昵称拼接唯一定位
    const leftNames = target.left.map(p => p.nickName).join(',');
    const rightNames = target.right.map(p => p.nickName).join(',');
    const realIndex = matchList.findIndex(item =>
      item.left.map(p => p.nickName).join(',') === leftNames &&
      item.right.map(p => p.nickName).join(',') === rightNames
    );
    if (realIndex === -1) return;
    matchList[realIndex].status = 'ready';
    this.setData({ matchList }, () => {
      this.filterMatchList();
    });
    // 同步到数据库
    const raceId = this.options && this.options.id;
    wx.cloud.database().collection('match').where({ raceId }).get({
      success: res => {
        if (res.data.length) {
          wx.cloud.database().collection('match').doc(res.data[0]._id).update({
            data: { matchList },
            success: () => {
              this.filterMatchList();
            }
          });
        }
      }
    });
  },
  onDisclaimerChange(e) {
    this.setData({ disclaimerChecked: e.detail.value.length > 0 });
  },
  onTabChange(e) {
    const idx = Number(e.currentTarget.dataset.index);
    if (idx === 2) {
      // 统计成绩，按个人统计
      this.calculateResults();
      this.setData({ selectedItemIndex: idx });
    } else {
      this.setData({ selectedItemIndex: idx });
    }
  },
  onOpenScoreModal(e) {
    const filteredIndex = e.currentTarget.dataset.index;
    const { filteredMatchList, matchList } = this.data;
    const target = filteredMatchList[filteredIndex];
    const leftNames = target.left.map(p => p.nickName).join(',');
    const rightNames = target.right.map(p => p.nickName).join(',');
    const realIndex = matchList.findIndex(item =>
      item.left.map(p => p.nickName).join(',') === leftNames &&
      item.right.map(p => p.nickName).join(',') === rightNames
    );
    if (realIndex === -1) return;
    const match = matchList[realIndex];
    this.setData({
      scoreModalVisible: true,
      scoreModalIndex: realIndex,
      scoreLeft: match.score ? match.score.left : '',
      scoreRight: match.score ? match.score.right : '',
      scoreModalLeft: match.left ? match.left.slice() : [],
      scoreModalRight: match.right ? match.right.slice() : []
    });
  },
  onScoreInput(e) {
    const { side } = e.currentTarget.dataset;
    const value = e.detail.value;
    
    // 只允许输入数字
    if (value && !/^\d*$/.test(value)) {
      wx.showToast({ title: '只能输入数字', icon: 'none' });
      return;
    }
    
    this.setData({ [side]: value });
  },
  onCloseScoreModal() {
    this.setData({ scoreModalVisible: false, scoreModalIndex: -1 });
  },
  onConfirmScoreModal() {
    const { scoreModalIndex, scoreLeft, scoreRight, matchList } = this.data;
    if (scoreLeft === '' || scoreRight === '') {
      wx.showToast({ title: '请填写完整比分', icon: 'none' });
      return;
    }
    // 新增：校验输入为数字
    if (isNaN(Number(scoreLeft)) || isNaN(Number(scoreRight))) {
      wx.showToast({ title: '比分只能输入数字', icon: 'none' });
      return;
    }
    matchList[scoreModalIndex].score = { left: Number(scoreLeft), right: Number(scoreRight) };
    matchList[scoreModalIndex].status = 'finished';
    // 判断是否全部结束
    const allFinished = matchList.every(item => item.status === 'finished');
    if (allFinished) {
      // 全部结束，更新比赛状态为"已完赛"
      const raceId = this.raceId;
      const raceData = this.localDataManager.getRace(raceId);
      if (raceData) {
        raceData.status = '已完赛';
        this.localDataManager.saveRace(raceData);
      }
      
      // 计算成绩
      this.calculateResults();
      
      // 自动切换到比赛成绩tab
      this.setData({
        selectedItemIndex: 2
      }, () => {
        // 滚动到页面顶部
        wx.pageScrollTo({
          scrollTop: 0,
          duration: 300
        });
      });
      wx.showToast({ title: '所有比赛已完成，已切换到比赛成绩', icon: 'success' });
    } else {
      wx.showToast({ title: '比分已保存', icon: 'success' });
    }
    
    this.setData({
      matchList,
      scoreModalVisible: false,
      scoreModalIndex: -1
    }, () => {
      this.setMatchProgress();
      this.filterMatchList();
    });
    // 新增：比分录入后同步更新本地存储
    const raceId = this.options && this.options.id;
    this.localDataManager.saveMatches(raceId, [{ raceId, matchList }]);
    this.filterMatchList();
  },
  updateCourtCountLimit() {
    const n = this.data.signupList.filter(item => item).length;
    let maxCourt = 1;
    if (n >= 16) maxCourt = 4;
    else if (n >= 12) maxCourt = 3;
    else if (n >= 8) maxCourt = 2;
    else maxCourt = 1;
    // 只更新maxCourtCount，不自动降档courtCount
    this.setData({ maxCourtCount: Math.max(1, maxCourt) });
  },
  onCourtCountChange(e) {
    this.setData({ courtCount: Number(e.detail.value) + 1 });
  },
  onAddCourt() {
    let { courtCount, maxCourtCount } = this.data;
    if (courtCount < maxCourtCount) {
      this.setData({ courtCount: courtCount + 1 });
    }
  },
  onSubCourt() {
    let { courtCount } = this.data;
    if (courtCount > 1) {
      this.setData({ courtCount: courtCount - 1 });
    }
  },
  onCourtRadioGroupChange(e) {
    if (!this.data.isCreator) {
      wx.showToast({ title: '只有创建人才能修改', icon: 'none' });
      return;
    }
    const value = Number(e.detail.value);
    this.setData({ courtCount: value });
    // 同步到本地存储
    const raceId = this.options && this.options.id;
    const raceData = this.localDataManager.getRace(raceId);
    if (raceData) {
      raceData.courtCount = value;
      this.localDataManager.saveRace(raceData);
      wx.showToast({ title: '场地数已更新' });
    } else {
      wx.showToast({ title: '比赛不存在', icon: 'none' });
    }
  },
  onBack() {
    // 返回到比赛列表页
    wx.navigateBack({
      fail: () => {
        // 如果返回失败，则跳转到列表页
        wx.switchTab({ url: '/pages/list/list' });
      }
    });
  },
  loadSignupList() {
    const raceId = this.options && this.options.id;
    if (!raceId) return;
    
    // 从本地存储加载报名列表
    const signupDataList = this.localDataManager.getSignups(raceId);
    let maxPlayers = this.data.maxPlayers || 8;
    
    // 创建固定长度的数组，保持位置信息
    let signupList = new Array(maxPlayers).fill(null);
    
    if (signupDataList && signupDataList.length > 0) {
      // 将报名数据按order放置到对应位置
      signupDataList.forEach(item => {
        if (typeof item.order === 'number' && item.order >= 0 && item.order < maxPlayers) {
          const signupItem = {};
          // 复制userInfo的所有属性
          if (item.userInfo) {
            for (let key in item.userInfo) {
              if (item.userInfo.hasOwnProperty(key)) {
                signupItem[key] = item.userInfo[key];
              }
            }
          }
          signupItem._id = item._id;
          signupItem.order = item.order;
          signupList[item.order] = signupItem;
        }
      });
    }
    
    let actualCount = signupList.filter(item => item !== null).length;
    
    if (actualCount > maxPlayers) {
      maxPlayers = actualCount;
      // 更新本地存储中的比赛信息
      const raceData = this.localDataManager.getRace(raceId);
      if (raceData) {
        raceData.maxPlayers = maxPlayers;
        this.localDataManager.saveRace(raceData);
      }
      // 重新调整数组长度
      while (signupList.length < maxPlayers) {
        signupList.push(null);
      }
    }
    
    // 获取比赛信息
    const raceData = this.localDataManager.getRace(raceId);
    const data2 = raceData || {};
    
    this.setData({
      signupList,
      signupCount: actualCount,
      appliedCount: actualCount,
      maxPlayers,
      raceTitle: data2.title || '',
      'raceInfo.totalNum': actualCount // 新增：同步报名人数
    }, this.updateSignupCount);
  },
  loadMatchList() {
    const raceId = this.options && this.options.id;
    if (!raceId) return;
    
    // 从本地存储加载比赛列表
    const matchData = this.localDataManager.getMatches(raceId);
    if (matchData && matchData.length) {
      // 检查数据格式：如果是对象数组且包含 matchList 属性，则取 matchList
      let matchList;
      if (matchData[0] && matchData[0].matchList) {
        matchList = matchData[0].matchList;
      } else {
        // 否则直接使用 matchData
        matchList = matchData;
      }
      this.setData({ matchList }, () => {
        this.setMatchProgress();
        this.filterMatchList();
        // 自动修正：如果比赛已完赛，强制统计成绩
        if (this.data.raceStatus === '已完赛' || this.data.selectedItemIndex === 2) {
          const matchList = this.data.matchList;
          const playerMap = {};
          this.data.signupList.filter(Boolean).forEach(player => {
            playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
          });
          matchList.forEach(match => {
            if (!match.score) return;
            const left = match.left;
            const right = match.right;
            let leftScore = match.score.left;
            let rightScore = match.score.right;
            if (leftScore > rightScore) {
              left.forEach(player => {
                if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
                playerMap[player.nickName].win += 1;
                playerMap[player.nickName].score += leftScore - rightScore;
              });
              right.forEach(player => {
                if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
                playerMap[player.nickName].lose += 1;
                playerMap[player.nickName].score -= leftScore - rightScore;
              });
            } else if (leftScore < rightScore) {
              right.forEach(player => {
                if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
                playerMap[player.nickName].win += 1;
                playerMap[player.nickName].score += rightScore - leftScore;
              });
              left.forEach(player => {
                if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
                playerMap[player.nickName].lose += 1;
                playerMap[player.nickName].score -= rightScore - leftScore;
              });
            }
          });
          const resultList = Object.values(playerMap);
          resultList.sort((a, b) => b.win - a.win || b.score - a.score);
          this.setData({ resultList });
        }
      });
    }
  },
  onEditTitle() {
    if (!this.data.isCreator) {
      wx.showToast({ title: '只有创建人才能修改', icon: 'none' });
      return;
    }
    this.setData({
      showEditTitleModal: true,
      editTitleValue: this.data.raceTitle || this.data.defaultRaceTitle || ''
    });
  },
  onEditTitleInput(e) {
    this.setData({
      editTitleValue: e.detail.value
    });
  },
  onConfirmEditTitle() {
    const newTitle = this.data.editTitleValue.trim();
    if (!newTitle) {
      wx.showToast({ title: '名称不能为空', icon: 'none' });
      return;
    }
    const raceId = this.options && this.options.id;
    
    // 更新本地存储中的比赛信息
    const raceData = this.localDataManager.getRace(raceId);
    if (raceData) {
      raceData.title = newTitle;
      this.localDataManager.saveRace(raceData);
      
      wx.showToast({ title: '名称已更新' });
      this.setData({
        raceTitle: newTitle,
        showEditTitleModal: false
      });
    } else {
      wx.showToast({ title: '比赛不存在', icon: 'none' });
    }
  },
  onCancelEditTitle() {
    this.setData({
      showEditTitleModal: false
    });
  },
  setMatchProgress() {
    const matchList = this.data.matchList || [];
    const finishedCount = matchList.filter(item => item.status === 'finished').length;
    this.setData({ finishedCount });
  },
  onScoreTabChange(e) {
    const index = e.currentTarget.dataset.index;
    this.setData({ scoreTabIndex: index }, this.filterMatchList);
  },
  onScoreRefresh() {
    wx.showLoading({ title: '刷新中...' });
    this.loadMatchList();
    setTimeout(() => { wx.hideLoading(); wx.showToast({ title: '已刷新', icon: 'success', duration: 800 }); }, 800);
  },
  filterMatchList() {
    const { matchList, scoreTabIndex } = this.data;
    let filtered = [];
    if (scoreTabIndex === 0) {
      filtered = matchList;
    } else if (scoreTabIndex === 1) {
      filtered = matchList.filter(item => item.status === 'ready' || item.status === 'playing');
    } else if (scoreTabIndex === 2) {
      filtered = matchList.filter(item => item.status === 'ready');
    } else if (scoreTabIndex === 3) {
      filtered = matchList.filter(item => item.status === 'playing');
    }
    const tabList = [
      { title: '全部', count: matchList.length },
      { title: '未结束', count: matchList.filter(item => item.status === 'ready' || item.status === 'playing').length },
      { title: '可以比赛', count: matchList.filter(item => item.status === 'ready').length },
      { title: '比赛中', count: matchList.filter(item => item.status === 'playing').length }
    ];
    this.setData({ filteredMatchList: filtered, scoreTabList: tabList });
  },
  onQuickSignup() {
    this.setData({ showQuickSignupModal: true, quickSignupText: '' });
  },
  onCloseQuickSignup() {
    this.setData({ showQuickSignupModal: false, quickSignupText: '' });
  },
  onQuickSignupInput(e) {
    this.setData({ quickSignupText: e.detail.value });
  },
  onConfirmQuickSignup() {
    const text = this.data.quickSignupText || '';
    // 逐行匹配，兼容多种点号和行首空格、全角空格、点号后空格
    const lines = text.split('\n').map(line => line.replace(/^\s+|\s+$/g, ''));
    const filterKeywords = ['场', '封车', '锁死', '钥匙'];
    // 允许点号后有任意空格，且点号可为.、．、。 、
    const names = lines
      .filter(line => /^[\s\u3000]*\d+[\.．。、]\s*[^\s]+/.test(line))
      .map(line => line.replace(/^[\s\u3000]*\d+[\.．。、]\s*/, ''))
      .filter(name => !filterKeywords.some(keyword => name.includes(keyword)));
    if (!names.length) {
      wx.showToast({ title: '请粘贴有效的接龙内容', icon: 'none' });
      return;
    }
    const defaultAvatar = '../../images/avatar_boy.png';
    const raceId = this.options && this.options.id;
    // 加 order 字段
    const signupList = names.map((name, idx) => ({ nickName: name, avatarUrl: defaultAvatar, gender: 'male', order: idx }));
    wx.showModal({
      title: '提示',
      content: '导入报名会清空原来的报名信息，是否导入？',
      confirmText: '导入',
      cancelText: '取消',
      success: (res) => {
        if (res.confirm) {
          console.log('[QuickSignup] 开始清空报名，raceId:', raceId);
          // 彻底清空报名，等待清空完成后再导入
          setTimeout(async () => { await this.importSignupBatch(signupList, raceId); }, 100);
        }
      }
    });
  },
  onQuickSignupBtn() {
    this.setData({ showQuickSignupModal: true });
  },
  async importSignupBatch(signupList, raceId) {

    // 清空现有报名
    this.localDataManager.clearSignups(raceId);
    
    // 批量添加到本地存储
    for (const item of signupList) {
      const signupData = {
        raceId,
        order: item.order,
        userInfo: {
          nickName: item.nickName,
          avatarUrl: item.avatarUrl,
          gender: item.gender
        }
      };
      this.localDataManager.addSignup(raceId, signupData);
    }
    
    wx.showToast({ title: '已导入报名', icon: 'success' });
    this.setData({ showQuickSignupModal: false, quickSignupText: '' });
    
    // 导入后调试输出报名顺序
    const signupDataList = this.localDataManager.getSignups(raceId);
    const debugList = (signupDataList || []).map(item => ({ order: item.order, nickName: item.userInfo.nickName }));

    this.loadSignupList();
  },
  onEditSignup(e) {
    const index = e.currentTarget.dataset.index;
    const { signupList } = this.data;
    const item = signupList[index];
    if (!item || !item.nickName) return;
    wx.showModal({
      title: '编辑报名昵称',
      editable: true,
      placeholderText: '请输入新昵称',
      content: item.nickName,
      success: (res) => {
        if (res.confirm && res.content && res.content !== item.nickName) {
          // 更新本地存储
          const raceId = this.options && this.options.id;
          const signupDataList = this.localDataManager.getSignups(raceId);
          const targetSignup = signupDataList.find(signup => 
            signup.userInfo.nickName === item.nickName && signup.order === item.order
          );
          
          if (targetSignup) {
            targetSignup.userInfo.nickName = res.content;
            this.localDataManager.updateSignup(raceId, targetSignup);
            wx.showToast({ title: '已修改' });
            this.loadSignupList();
          } else {
            wx.showToast({ title: '修改失败', icon: 'none' });
          }
        }
      }
    });
  },
  // 编辑报名弹窗输入
  onEditSignupNameInput(e) {
    // 实时更新 editSignupName，确保输入框和数据同步
    this.setData({ editSignupName: e.detail.value });
  },
  onEditSignupGenderSelect(e) {
    this.setData({ editSignupGender: e.currentTarget.dataset.gender });
  },
  onConfirmEditSignup() {
    const { editSignupIndex, editSignupName, editSignupGender, signupList } = this.data;
    const item = signupList[editSignupIndex];
    if (!item || !editSignupName.trim() || !item._id) {
      wx.showToast({ title: '数据异常', icon: 'none' });
      return;
    }
    // 根据性别切换默认头像
    let avatarUrl = item.avatarUrl;
    if (editSignupGender === 'female') {
      avatarUrl = '../../images/avatar_girl.png';
    } else if (editSignupGender === 'male') {
      avatarUrl = '../../images/avatar_boy.png';
    }
    // 更新本地存储中的报名信息
    const raceId = this.options && this.options.id;
    const signupDataList = this.localDataManager.getSignups(raceId);
    const targetSignup = signupDataList.find(signup => signup._id === item._id);
    
    if (targetSignup) {
      targetSignup.userInfo.nickName = editSignupName;
      targetSignup.userInfo.gender = editSignupGender;
      targetSignup.userInfo.avatarUrl = avatarUrl;
      this.localDataManager.updateSignup(raceId, targetSignup);
      
      wx.showToast({ title: '已修改' });
      this.setData({ showEditSignupModal: false });
      this.loadSignupList();
    } else {
      wx.showToast({ title: '修改失败', icon: 'none' });
      console.error('报名信息修改失败：未找到对应记录');
    }
  },
  onCancelEditSignup() {
    this.setData({ showEditSignupModal: false });
  },
  onShowMatchCountTip() {
    wx.showModal({
      title: '比赛局数说明',
      content: '比赛局数是系统根据人数自动生成的，保证每人轮空均等，配对公平，每人比赛数量相等。自定义局数请根据实际需求设置，建议为偶数。',
      showCancel: false
    });
  },
  calculateResults() {
    const matchList = this.data.matchList || [];
    const playerMap = {};
    // 初始化所有参赛人
    this.data.signupList.filter(Boolean).forEach(player => {
      playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
    });
    matchList.forEach(match => {
      if (!match.score) return;
      // 左右两边可能是单人或双人
      const left = match.left;
      const right = match.right;
      let leftScore = match.score.left;
      let rightScore = match.score.right;
      // 胜负统计
      if (leftScore > rightScore) {
        left.forEach(player => {
          if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
          playerMap[player.nickName].win += 1;
          playerMap[player.nickName].score += leftScore - rightScore;
        });
        right.forEach(player => {
          if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
          playerMap[player.nickName].lose += 1;
          playerMap[player.nickName].score -= leftScore - rightScore;
        });
      } else if (leftScore < rightScore) {
        right.forEach(player => {
          if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
          playerMap[player.nickName].win += 1;
          playerMap[player.nickName].score += rightScore - leftScore;
        });
        left.forEach(player => {
          if (!playerMap[player.nickName]) playerMap[player.nickName] = { name: player.nickName, win: 0, lose: 0, score: 0, avatarUrl: player.avatarUrl, gender: player.gender };
          playerMap[player.nickName].lose += 1;
          playerMap[player.nickName].score -= rightScore - leftScore;
        });
      }
    });
    // 排序：先按胜局，再按净胜分降序
    const resultList = Object.values(playerMap).sort((a, b) => b.win - a.win || b.score - a.score);
    this.setData({ resultList });
  }
});